const WebSocket = require('ws');
const http = require('http');

// 测试配置
const CONFIG = {
    server: {
        host: 'localhost',
        port: 3001
    },
    testUser: {
        phone: '13800138000',
        passwordHash: 'e10adc3949ba59abbe56e057f20f883e' // 123456的MD5
    }
};

class PrivateMessageNotificationTester {
    constructor() {
        this.ws = null;
        this.userId = null;
        this.token = null;
        this.testResults = [];
        this.receivedMessages = [];
    }

    async runTest() {
        console.log('💬 开始私信通知完整功能测试...\n');
        console.log('测试目标：验证两种私信通知情况\n');
        console.log('1. 对方在线时，直接推送给对方');
        console.log('2. 对方不在线时，上线时检测并推送未读私信\n');

        try {
            await this.testHttpLogin();
            await this.testWebSocketConnection();
            await this.testQueryCharacters();
            await this.testSelectCharacter();
            await this.testWaitForNotifications();
            await this.testDisconnect();
            this.printTestSummary();
        } catch (error) {
            console.error('❌ 测试执行失败:', error.message);
            this.addTestResult('测试执行', false, error.message);
            this.printTestSummary();
        }
    }

    async testHttpLogin() {
        console.log('🔐 步骤1: HTTP登录测试...');

        try {
            const loginData = await this.httpRequest('/api/user/login', {
                phone: CONFIG.testUser.phone,
                pwd: CONFIG.testUser.passwordHash
            });

            if (loginData.code === 0 && loginData.data) {
                this.userId = loginData.data.userId;
                this.token = loginData.data.token;
                console.log('✅ 登录成功: userId=' + this.userId);
                this.addTestResult('HTTP登录测试', true, '登录成功，userId=' + this.userId);
            } else {
                throw new Error(`登录失败: ${loginData.msg || '未知错误'}`);
            }
        } catch (error) {
            console.error('❌ HTTP登录失败:', error.message);
            this.addTestResult('HTTP登录测试', false, error.message);
            throw error;
        }
    }

    async testWebSocketConnection() {
        console.log('🔌 步骤2: WebSocket连接测试...');

        return new Promise((resolve, reject) => {
            const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}/user-service/websocket?t=${this.token}`;
            this.ws = new WebSocket(wsUrl);

            this.ws.on('open', async () => {
                console.log('✅ WebSocket连接成功');
                this.addTestResult('WebSocket连接测试', true, '连接成功');
                resolve();
            });

            this.ws.on('error', (error) => {
                console.log('❌ WebSocket连接失败:', error.message);
                this.addTestResult('WebSocket连接测试', false, error.message);
                reject(error);
            });

            this.ws.on('close', () => {
                console.log('🔌 WebSocket连接已关闭');
            });

            setTimeout(() => {
                if (this.ws.readyState === WebSocket.CONNECTING) {
                    reject(new Error('WebSocket连接超时'));
                }
            }, 10000);
        });
    }

    async testQueryCharacters() {
        console.log('📋 步骤3: 查询角色列表...');

        return new Promise((resolve, reject) => {
            const timeoutMs = 10000;
            const timeout = setTimeout(() => {
                this.ws.removeListener('message', responseHandler);
                reject(new Error(`等待act_id 3 响应超时`));
            }, timeoutMs);

            const responseHandler = (raw) => {
                try {
                    const message = JSON.parse(raw.toString());
                    if (message.act_id === 3) {
                        clearTimeout(timeout);
                        this.ws.removeListener('message', responseHandler);

                        const list = message.roleList && Array.isArray(message.roleList) ? message.roleList : [];
                        this.characters = list;

                        if (list.length) {
                            console.log(`✅ 查询成功，共${message.roleCount || list.length}个角色`);
                            this.addTestResult('查询角色列表测试', true, '查询成功，共' + (message.roleCount || list.length) + '个角色');
                            resolve();
                        } else {
                            reject(new Error('没有找到角色'));
                        }
                    }
                } catch (_) { }
            };

            this.ws.on('message', responseHandler);
            this.ws.send(JSON.stringify({ c: 3, d: null }));
        });
    }

    async testSelectCharacter() {
        console.log('🎯 步骤4: 选择角色...');

        if (!this.characters || this.characters.length === 0) {
            throw new Error('没有可选择的角色');
        }

        const roleId = this.characters[0].id;

        return new Promise((resolve, reject) => {
            const timeoutMs = 10000;
            const timeout = setTimeout(() => {
                this.ws.removeListener('message', responseHandler);
                reject(new Error(`等待act_id 4 响应超时`));
            }, timeoutMs);

            const responseHandler = (data) => {
                try {
                    const message = JSON.parse(data.toString());
                    if (message.act_id === 4) {
                        clearTimeout(timeout);
                        this.ws.removeListener('message', responseHandler);

                        if (message.code === 0) {
                            console.log(`✅ 角色选择成功: ID=${roleId}`);
                            this.addTestResult('选择角色测试', true, '角色选择成功，ID=' + roleId);
                            resolve();
                        } else {
                            reject(new Error(`角色选择失败: ${message.msg}`));
                        }
                    }
                } catch (_) { }
            };

            this.ws.on('message', responseHandler);
            this.ws.send(JSON.stringify({ c: 4, d: { characterId: roleId } }));
        });
    }

    async testWaitForNotifications() {
        console.log('💬 步骤5: 等待私信通知...');
        console.log('💡 提示：此测试会等待30秒，检测是否有未读私信通知');
        console.log('💡 如果收到 {"act_id":10,"info_id":发送者ID,"state":1或2} 则表示测试成功\n');

        return new Promise((resolve) => {
            const timeoutMs = 30000; // 30秒超时
            const timeout = setTimeout(() => {
                this.ws.removeListener('message', responseHandler);
                console.log('⏰ 等待超时，未收到私信通知');
                if (this.receivedMessages.length > 0) {
                    console.log('📨 但之前收到了以下消息:');
                    this.receivedMessages.forEach((msg, index) => {
                        console.log(`  ${index + 1}. ${JSON.stringify(msg)}`);
                    });
                    this.addTestResult('私信通知测试', true, `收到${this.receivedMessages.length}条消息`);
                } else {
                    this.addTestResult('私信通知测试', true, '等待超时，无未读私信');
                }
                resolve();
            }, timeoutMs);

            const responseHandler = (data) => {
                try {
                    const message = JSON.parse(data.toString());

                    // 记录所有收到的消息
                    this.receivedMessages.push(message);

                    if (message.act_id === 10) {
                        console.log('🎉 收到私信通知！');
                        console.log('📨 消息内容:', JSON.stringify(message, null, 2));

                        // 验证消息格式
                        if (message.info_id && (message.state === 1 || message.state === 2)) {
                            const messageType = message.state === 1 ? '系统消息' : '玩家消息';
                            console.log(`✅ 私信通知格式正确：${messageType} (info_id=${message.info_id}, state=${message.state})`);

                            // 如果是系统消息，检查info_id是否为1000
                            if (message.state === 1 && message.info_id === 1000) {
                                console.log('✅ 系统消息格式完全正确');
                            }

                            this.addTestResult('私信通知测试', true, `收到正确格式的${messageType}`);
                        } else {
                            console.log('⚠️ 私信通知格式不符合预期');
                            this.addTestResult('私信通知测试', false, '私信通知格式不符合预期');
                        }

                        // 收到通知后继续等待，看是否还有其他通知
                    }
                } catch (_) { }
            };

            this.ws.on('message', responseHandler);
        });
    }

    async testDisconnect() {
        console.log('\n🔌 步骤6: 断开连接...');
        try {
            this.ws?.close();
        } catch (_) { }
        console.log('✅ 连接已断开');
    }

    addTestResult(testName, success, message) {
        this.testResults.push({ testName, success, message });
    }

    printTestSummary() {
        console.log('\n📊 测试结果汇总:');
        console.log('='.repeat(50));

        const totalTests = this.testResults.length;
        const passedTests = this.testResults.filter(r => r.success).length;
        const failedTests = totalTests - passedTests;

        this.testResults.forEach(result => {
            const status = result.success ? '✅' : '❌';
            console.log(`${status} ${result.testName}: ${result.message}`);
        });

        console.log('='.repeat(50));
        console.log(`📈 总计: ${totalTests} 个测试`);
        console.log(`✅ 通过: ${passedTests} 个`);
        console.log(`❌ 失败: ${failedTests} 个`);

        if (this.receivedMessages.length > 0) {
            console.log('\n📨 收到的消息统计:');
            const act10Count = this.receivedMessages.filter(m => m.act_id === 10).length;
            const otherCount = this.receivedMessages.length - act10Count;
            console.log(`  - act_id=10 (私信通知): ${act10Count} 条`);
            console.log(`  - 其他消息: ${otherCount} 条`);
        }

        if (failedTests === 0) {
            console.log('\n🎉 所有测试通过！私信通知功能正常工作。');
        } else {
            console.log('\n⚠️ 部分测试失败，请检查相关功能。');
        }
    }

    async httpRequest(path, body = null) {
        const options = {
            hostname: CONFIG.server.host,
            port: CONFIG.server.port,
            path: path,
            method: body ? 'POST' : 'GET',
            headers: { 'Content-Type': 'application/json' }
        };

        return new Promise((resolve, reject) => {
            const req = http.request(options, (res) => {
                let data = '';
                res.on('data', (chunk) => {
                    data += chunk;
                });
                res.on('end', () => {
                    try {
                        resolve(JSON.parse(data));
                    } catch (e) {
                        reject(new Error('响应解析失败'));
                    }
                });
            });

            req.on('error', (err) => reject(err));
            if (body) req.write(JSON.stringify(body));
            req.end();
        });
    }
}

// 运行测试
(async () => {
    const tester = new PrivateMessageNotificationTester();
    await tester.runTest();
})();
